import websocket
import json
import time
import requests
import os
from urllib.parse import urlparse
from crc16 import pack_data
from util import parse_command_to_ascII, logger
from setting import *
import paho.mqtt.client as mqtt

def mqtt_send_data_to_main_station(data):

        '''发送数据到mqtt
        data :{
            "type": "callback"
            "data":{
                "task_type": "gateways_info",
                "task_id": "1", 																	# 任务ID号
                "task_status": "receive",                                                           # receive 接收 success 成功 fail 失败
                "notes": null,																		# 回调说明，任务失败原因
                "result": null,																		# 回调结果 有回调结果传结果
            }
        }
        '''
        # 连接 MQTT 代理
        client = mqtt.Client()

        # 建立连接
        client.connect(MQTT_LOCAL_HOST, MQTT_LOCAL_PORT, 60)

        payload = json.dumps(data)

        # 发布数据到指定主题
        client.publish(MQTT_LOCAL_PUBLISH_TOPIC, payload)

        # 断开 MQTT 连接
        client.disconnect()

def downland_remote_files(file_url):

    # 解析连接获取文件名
    filename = os.path.basename(urlparse(file_url).path)

    # 检查当前文件夹是否已存在相同文件名的文件
    if os.path.exists(filename):

        logger.info(f"{filename} 已存在，无需下载")

        return 1
    else:
        response = requests.get(file_url)
        
        # 检查请求是否成功
        if response.status_code == 200:
            with open(filename, 'wb') as file:
                file.write(response.content)
            logger.info(f"成功保存文件为 {filename}")
            return 1
        else:
            print("文件下载失败")

            logger.info(f"文件下载失败: {filename}")

            return 0


class UpdateSensorWebSocketClient:
    def __init__(self, devaddr, task_id, file_path="stm32L476RGT6.bin"):

        self.url = f"ws://127.0.0.1:8080/ws/uplink/{devaddr}"
        logger.info(f"建立WS升级通道: {self.url}")
        self.websocket = None
        self.step = "wait_return_version"
        self.total_block = self.total_blocks(file_path)
        self.file_path = file_path
        self.task_id = task_id

    
    @staticmethod
    def total_blocks(file_path): # 返回文件分为多少块

        block_size = 64

        with open(file_path, 'rb') as file:

            file_data = file.read()
            
            # 计算总块数
            total_blocks = (len(file_data) + block_size - 1) // block_size

        return total_blocks

    def get_version(self): # TODO

        return self.file_path.replace(".bin")
    
    @staticmethod
    def get_file_block(file_path, block_index): # 指定文件，指定第几块数反回对应的二进制
        block_size = 64  # 块大小为128bit
        
        with open(file_path, 'rb') as file:
            file_data = file.read()
            
            # 计算总块数
            total_blocks = (len(file_data) + block_size - 1) // block_size
            
            # "文件为空"
            if total_blocks == 0:

                return None
            
            # 计算块的起始和结束位置
            start_pos = block_index * block_size

            end_pos = start_pos + block_size
            
            # 获取指定块的数据
            block_data = file_data[start_pos:end_pos]
            
            # 如果最后一块不足128bit，用\xff进行填充
            if block_index == total_blocks - 1 and len(block_data) < block_size:

                padding = block_size - len(block_data)
                
                block_data += b'\xff' * padding
            
            return block_data


    def on_open(self, ws):
        logger.info("WebSocket connection established.")

        # 基站下升级指令
        upgrade_request = parse_command_to_ascII(pack_data(bytearray([0x06, 0x01, 0x07, 0x15, 0x01])))
        
        self.websocket.send(json.dumps({'data': upgrade_request, 'port': 12}))
        time.sleep(1)
        self.websocket.send(json.dumps({'data': upgrade_request, 'port': 12}))
        time.sleep(1)
        self.websocket.send(json.dumps({'data': upgrade_request, 'port': 12}))

    def on_message(self, ws, message):
        logger.info(f"Received: {message}")

        # 在这里处理接收到的消息
        # ...

        message = json.loads(message)

        message_text = message["text"]

        # if self.step == "wait_return_version" and  message_text[2:4] == "01": # 传感器应答版本查询

        #     if message_text[8:12] == self.get_version():

        #         logger.info(f"--{message['devaddr']}: 当前传感器版本已经是最新版本")

        #         self.disconnect()

        #     else: # 3.基站下发新版本通知

        #         command = parse_command_to_ascII(pack_data(bytearray([0x06, 0x02, 0x00, 0x02, 0x00, 0x02])))

        #         self.websocket.send(json.dumps({'data': command, 'port': 12}))

        #         logger.info(f"--{message['devaddr']}: 基站下发新版本通知")

        #         self.step = "wait_request_packet"

        # elif self.step == "wait_sensor_response_new_version_notification" and  message_text[2:4] == "02": # 传感器应答新版本通知

        #     self.step = "wait_request_packet"
        #     logger.info(f"{message['devaddr']}: 收到传感器应答新版本通知")

        # elif self.step == "wait_request_packet" and message_text[2:4] == "03": # 传感器发送请求数据包
        if message_text[2:4] == "03": # 传感器发送请求数据包

            command = bytearray([0x06, 0x03])

            total = '{:04x}'.format(self.total_block)

            # 添加总包数
            command+= eval("b'\\x" + total[0:2] + "'")
            command+= eval("b'\\x" + total[2:4] + "'")

            # 添加本包数
            command+= eval("b'\\x" + message_text[8:10] + "'")
            command+= eval("b'\\x" + message_text[10:12] + "'")

            # 添加长度
            command+= b"\x40"

            # 添加数据
            command += self.get_file_block(self.file_path, int(message_text[8:12], 16)-1)

            logger.info(f"--{message['devaddr']}: 第{int(message_text[8:12], 16)}包-{command}")
            
            # 解析命令成发送状态
            command = parse_command_to_ascII(pack_data(command))

            logger.info(f"--{message['devaddr']}: 第{int(message_text[8:12], 16)}包-{command}")

            self.websocket.send(json.dumps({'data': command, 'port': 12}))

            logger.info(f"--{message['devaddr']}: 第{int(message_text[8:12], 16)}包数据发送成功")


        # elif self.step == "wait_request_packet" and message_text[0:8] == "11050002": # 传感器升级结果回调
        elif message_text[2:4] == "05": # 传感器升级结果回调

            if int(message_text[8:12], 16) == 1:

                logger.info(f"{message['devaddr']}: 升级成功")

            if int(message_text[8:12], 16) == 0:

                logger.error(f"{message['devaddr']}: 升级失败")

            self.disconnect()

    def on_error(self, ws, error):
        logger.info(f"Error: {error}")
        raise

    def on_close(self, ws, XX, YY):
        logger.info("WebSocket connection closed.")

    def connect(self):
        # 连接至 WebSocket 服务器
        self.websocket = websocket.WebSocketApp(
            self.url,
            on_open=self.on_open,
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close
        )

        # 监听并处理 WebSocket 事件
        self.websocket.run_forever()

    def disconnect(self):
        self.websocket.close()


if __name__ == "__main__":

    pass